ArrayList<E> is a dynamic array implementation of the List interface in Java. It stores elements contiguously in memory and automatically resizes as elements are added. The generic type parameter E specifies the type of elements stored, providing compile-time type safety.
get(index) and set(index, value) in O(1) time.null values.E enforces type safety (no casts on retrieval).ConcurrentModificationException.// Create with inferred type
ArrayList<String> names = new ArrayList<>();
// Create with initial capacity (reduces resizing if you know the size)
ArrayList<Integer> nums = new ArrayList<>(100);
// Add elements
names.add("Ada");
names.add("Grace");
names.add(1, "Linus"); // insert at index 1
// Access and modify
String first = names.get(0); // O(1)
names.set(2, "Hopper"); // O(1)
// Remove by index or by value
names.remove(1); // O(n) shift
names.remove("Ada"); // O(n) search then shift
// Search
boolean hasGrace = names.contains("Grace"); // O(n)
int idx = names.indexOf("Grace"); // O(n)
// Bulk operations
ArrayList<String> more = new ArrayList<>();
more.add("Edsger");
more.add("Barbara");
names.addAll(more);
// Iteration
for (String s : names) {
System.out.println(s);
}
// Using an Iterator (supports safe removal during iteration)
Iterator<String> it = names.iterator();
while (it.hasNext()) {
String s = it.next();
if (s.startsWith("B")) {
it.remove(); // safe structural change
}
}
// Sorting
names.sort(Comparator.naturalOrder());
// or
Collections.sort(names);
// Convert to array
String[] arr = names.toArray(new String[0]);
// Capacity management
names.ensureCapacity(1000);
names.trimToSize();
Internally, capacity grows when needed (commonly by ~1.5x). Pre-sizing with an appropriate initial capacity or using ensureCapacity can reduce reallocations and copying.
Consider LinkedList<E> when frequent insertions/removals in the middle dominate and indexed access is rare. Prefer arrays when the size is fixed and primitive storage is required (to avoid autoboxing overhead).
ArrayList<E> uses generics for compile-time type checks. For example, ArrayList<String> rejects non-String elements. Due to type erasure, the runtime representation does not retain E’s type parameter, but compile-time safety prevents class cast errors on retrieval.
Iterators over an ArrayList are fail-fast: if the list is structurally modified outside the iterator after its creation, operations like next() may throw ConcurrentModificationException. Use the iterator’s remove() for safe removal during iteration.
ArrayList require external synchronization.Collections.synchronizedList(new ArrayList<>()) or using CopyOnWriteArrayList for read-heavy, write-light workloads.subList(from, to) returns a view backed by the original list; structural changes to either affect the other. To copy, use new ArrayList<>(list.subList(...)).contains and remove(Object) rely on equals; implement it properly for custom types.ArrayList holds references; when storing boxed primitives (e.g., Integer), consider boxing overhead.ensureCapacity when the target size is known to minimize resizes; call trimToSize to reduce memory footprint when growth is complete.